package cz.proks.easyhelpdesk.gae.core.util;

import java.util.Calendar;
import java.util.Date;


public class Random {
	private final static char[] ALPHABET = new char[128];
	
	static {		
		for(int i=48; i<= 57; i++) ALPHABET[i] = (char) i; // 0-9
        for(int i=65; i<= 90; i++) ALPHABET[i] = (char) i; // A-Z
        for(int i=97; i<=122; i++) ALPHABET[i] = (char) i; // a-z
	}
	
	private final static int DEFAULT_STRING_LENGTH = 32;
	private final static int DEFAULT_NUMBER_MINIMUM = 0;
	private final static int DEFAULT_NUMBER_MAXIMUM = 100;
	
	private final java.util.Random random;		
	
	public Random() {
		random = new java.util.Random();		
	}
	
	/** 
	 * @return Random number between defined minimum (0) and maximum (100) inclusive.
	 */
	public int randomInt() {
		return randomInt(DEFAULT_NUMBER_MINIMUM, DEFAULT_NUMBER_MAXIMUM);
	}
	
	/**
	 * @param max Maximum number which can be returned
	 * @return Random number between defined minimum (0) and <code>max</code>.
	 */
	public int randomInt(int max) {
		return randomInt(DEFAULT_NUMBER_MINIMUM, max);		
	}
	
	/**
	 * @param min Minimum number which can be returned
	 * @param max Maximum number which can be returned
	 * @return Random number between defined <code>min</code> and <code>max</code>.
	 */
	public int randomInt(int min, int max) {
		return (int) randomLong(min, max);
	}
	
	/** 
	 * @return Random number between defined minimum (0) and maximum (100) inclusive.
	 */
	public long randomLong() {
		return randomLong(DEFAULT_NUMBER_MINIMUM, DEFAULT_NUMBER_MAXIMUM);
	}
	
	/**
	 * @param max Maximum number which can be returned
	 * @return Random number between defined minimum (0) and <code>max</code>.
	 */
	public long randomLong(long max) {
		return randomLong(DEFAULT_NUMBER_MINIMUM, max);
	}
	
	/**
	 * @param min Minimum number which can be returned
	 * @param max Maximum number which can be returned
	 * @return Random number between defined <code>min</code> and <code>max</code>.
	 */
	public long randomLong(long min, long max) {
		return Math.round(randomDouble(min, max));
	}
	
	/** 
	 * @return Random number between defined minimum (0) and maximum (100) inclusive.
	 */
	public float randomFloat() {
		return randomFloat(DEFAULT_NUMBER_MINIMUM, DEFAULT_NUMBER_MAXIMUM);
	}
	
	/**
	 * @param max Maximum number which can be returned
	 * @return Random number between defined minimum (0) and <code>max</code>.
	 */
	public float randomFloat(float max) {
		return randomFloat(DEFAULT_NUMBER_MINIMUM, max);
	}
	
	/**
	 * @param min Minimum number which can be returned
	 * @param max Maximum number which can be returned
	 * @return Random number between defined <code>min</code> and <code>max</code>.
	 */
	public float randomFloat(float min, float max) {
		return (float) randomDouble(min, max);
	}
	
	/** 
	 * @return Random number between defined minimum (0) and maximum (100) inclusive.
	 */
	public double randomDouble() {
		return randomDouble(DEFAULT_NUMBER_MINIMUM, DEFAULT_NUMBER_MAXIMUM);
	}
	
	/**
	 * @param max Maximum number which can be returned
	 * @return Random number between defined minimum (0) and <code>max</code>.
	 */
	public double randomDouble(double max) {
		return randomDouble(DEFAULT_NUMBER_MINIMUM, max);
	}
	
	/**
	 * @param min Minimum number which can be returned
	 * @param max Maximum number which can be returned
	 * @return Random number between defined <code>min</code> and <code>max</code>.
	 */
	public double randomDouble(double min, double max) {
		if (min > max) {
			double lowMax = max;
			max = min;
			min = lowMax;
		}
			
		return (random.nextDouble() * (max - min) + min);
	}
	
	/**
	 * @return Random generated strign which consist of A-Z, 0-9, a-z symbols and length of defined size (32)
	 */
	public String randomString() {
		return randomString(DEFAULT_STRING_LENGTH);
	}
	
	/**
	 * @param length Length of random generated string
	 * @return Random generated strign which consist of A-Z, 0-9, a-z symbols
	 */
	public String randomString(int length) {
		StringBuilder sb = new StringBuilder(length);
		int alphabetLength = ALPHABET.length;
		
		for (int i = 0; i < length; i++)
			sb.append(ALPHABET[randomInt(0, alphabetLength - 1)]);
		
		return sb.toString();
	}
	
	/**
	 * @return Random date from 00:00:00:000 to 23:59:59:999 of this day
	 */
	public Date randomDate() {
		Calendar calendar = Calendar.getInstance();
		
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		
		Date min = calendar.getTime();
		
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		
		Date max = calendar.getTime();
		
		return randomDate(min, max);		
	}
	
	/**
	 * @param min Minimal date which can be returned
	 * @param max Maximal date which can be returned
	 * @return Random date between <code>min</code> and <code>max</code> dates
	 */
	public Date randomDate(Date min, Date max) {
		if (min == null || max == null)
			return null;
		
		long startTime = min.getTime();
		long endTime = max.getTime();
		
		Date date = new Date(randomLong(startTime, endTime));
		return date;
	}

}
